#!/usr/bin/env python
# -*- encoding: utf-8 -*-
'''
@NAME          : ssl_renew_by_api.py
@TIME          : 2024/12/24 11:23:08
@AUTHOR        : chenlip
@VERSION       : 0.0.1
@DESCRIPTION   : 使用腾讯云Python API自动续期ssl证书
'''
# --------------------------引用--------------------------
import os, sys, json
import json,base64,os
from time import time,sleep
from tencentcloud.common import credential
from tencentcloud.common.profile.client_profile import ClientProfile
from tencentcloud.common.profile.http_profile import HttpProfile
from tencentcloud.common.exception.tencent_cloud_sdk_exception import TencentCloudSDKException
from tencentcloud.ssl.v20191205 import ssl_client, models
# --------------------------引用--------------------------

class TC_SSL_ACT:
    """
    使用腾讯云API自动续期ssl证书
    环境：
        腾讯云账户信息：(读取secret.json)
        {
            "userid": "apiuser",
            "SecretId": "AKIDe7MvGbsBcx54sssss",
            "SecretKey": "uwrZ5NssdfadsfYgoy",
            "token": "",
            "service": "ssl",
            "host": "ssl.tencentcloudapi.com",
            "region": "",
            "Version": "2019-12-05"
        }

        web服务器信息：
        1. 服务器地址：43.131.252.100
        2. 服务器用户名：root
        3. 服务器密码：123456
        相关域名：
            - chenlp.cc
            - 51epub.com
            - shushanyoulu.com
            - wben.cc
    功能：
        1. 查询过期的证书列表
        2. 申请新的证书
        3. 下载新的证书
        4. 更新到指定服务器的指定目录下的证书
    """
    def __init__(self):
        '''
            初始化, 读取腾讯云账户信息(读取secret.json)
        '''
        _secssl = json.load(open('secret.json'))
        self.userid = _secssl["userid"]
        self.SecretId = _secssl["SecretId"]
        self.SecretKey = _secssl["SecretKey"]
        self.token = _secssl["token"]
        self.service = _secssl["service"]
        self.host = _secssl["host"]
        self.region = _secssl["region"]
        self.Version = _secssl["Version"]

        self.sslpath = os.path.join(os.getcwd(), 'ssl')
        if not os.path.exists(self.sslpath):
            os.mkdir(self.sslpath)
        
        self.cred = credential.Credential(self.SecretId, self.SecretKey)
        self.httpProfile = HttpProfile()
        self.httpProfile.endpoint = self.host
        self.clientProfile = ClientProfile()
        self.clientProfile.httpProfile = self.httpProfile

        self.client = ssl_client.SslClient(self.cred, "", self.clientProfile)
        

    def query_expiring_ssl(self, isfilter:int=1) -> list:
        '''
            查询过期的证书列表
            参考：https://cloud.tencent.com/document/api/400/41671
            :Args:
                - isfilter: int, 是否过滤过期证书, 0:不过滤, 1:过滤
            :Return:
                - res: list, 过期证书列表,例如：
                
                [['域名-Domain','过期日期-CertEndTime','证书id-CertificateId','是否可续费-RenewAble','存在的续费证书ID-HasRenewOrder'],....]
        '''
        try:
            req = models.DescribeCertificatesRequest()
            params = {
                "Limit": 1000,
                "CertificateStatus": [1],
                "FilterExpiring": isfilter
            }
            req.from_json_string(json.dumps(params))
            resp = self.client.DescribeCertificates(req)
            # print(resp.to_json_string())
            res = []
            for r in resp.Certificates:
                res.append([r.Domain, r.CertEndTime, r.CertificateId, r.RenewAble, r.HasRenewOrder])
            return res
        except TencentCloudSDKException as err:
            print(err)
            return []
        

    # query_expiring_ssl

    def renew_ssl(self, domain:str, cert_id:str=None) -> str:
        '''
            申请免费新的证书，续期ssl证书
            参考：https://cloud.tencent.com/document/api/400/41678
            :Args:
                - domain: str, 域名
                - cert_id: str, 原来的证书ID

            :Return:
                返回新的证书 ID。
        '''
        _cid = ''
        if cert_id!=None: _cid = cert_id

        # 申请新的证书
        try:
            req = models.ApplyCertificateRequest()
            params = {
                "DvAuthMethod": "DNS_AUTO",
                "DomainName": domain,
                "OldCertificateId": _cid, # 原来的证书ID
                "DeleteDnsAutoRecord": True # 是否删除DNS记录
            }
            req.from_json_string(json.dumps(params))
            resp = self.client.ApplyCertificate(req)
            print(resp.to_json_string())
            _cid = resp.CertificateId

        except TencentCloudSDKException as err:
            print(err)

        return _cid

    # renew_ssl

    def download_ssl(self, cid:str, domain_name:str) -> str:
        '''
            下载新的证书
            :Args:
                - cid: 证书ID
                - domain_name: 域名
            :Return:
                - cert_path: str, 证书文件路径,当前目录下的ssl目录下(self.sslpath)
        '''
        # 下载新的证书
        _cert_zip = domain_name + '.zip'
        _cert_path = os.path.join(self.sslpath, _cert_zip)
        # 下载证书
        try:
            req = models.DownloadCertificateRequest()
            params = {
                "CertificateId": cid
            }
            req.from_json_string(json.dumps(params))
            resp = self.client.DownloadCertificate(req)
            response2 = json.loads(resp.to_json_string())
            # print(response2['Content'])
            content = response2['Content']
            with open(_cert_path, "wb") as f:
                f.write(base64.b64decode(content))
                f.close()
            # print(resp.to_json_string())
        except TencentCloudSDKException as err:
            print(err)

        return _cert_path
        

    # download_ssl

    def update_ssl_server(self, domain:str, cert_path:str):
        '''
            更新到指定服务器的指定目录下的证书
            :Args:
                - domain: str, 域名
                - cert_path: str, 证书文件路径
            :Return:
                - status: bool, 更新状态
        '''
        pass



if __name__ == '__main__':
    # 测试获取过期证书列表
    tc = TC_SSL_ACT()
    res = tc.query_expiring_ssl()
    print(res)

    # 测试下载证书
    ssl_fn = tc.download_ssl('DljlJCxE', 'chenlp.cc')
    print(ssl_fn)
